/*
 *  ScrollBar.cpp
 *  Fridge
 *
 *  Created by Jeremy Abel on 7/3/12.
 *  Copyright 2012 __MyCompanyName__. All rights reserved.
 *
 */

// Main header
#include "../Main.h"

//My Header
#include "ScrollBar.h"

// Fridge
#include "../Controller/Controller_Main.h"
#include "../Input.h"
#include "../MathsHelper.h"

static const u_int uSCROLLBAR_BACKGROUND	= 0xEAEAEAFF;

ScrollBar::ScrollBar( Widget* pxParent ) : Widget( pxParent )
{
	m_bEnabled = false;
	m_bHorizontal = false;
	m_bUsingBothBars = false;
	m_bMouseDownState = false;
	m_iMouseStartOffset = 0;
	m_iMinTrackPos = 0;
	m_iMaxTrackPos = 0;
	m_uScrollHandleLength = 0;
	m_iScrollbarOffset = 0;
	m_iParentVisableSize = 0;
	m_uParentContentSize = 0;
	m_iScrollDragStartOffset = 0;
	
	m_pxScrollbarButton = new Button( NULL );
	m_pxScrollbarButton->SetFlatStyle( false );
	m_pxScrollbarButton->SetEnabled( false );
	m_pxScrollbarButton->SetVisible( false );
	m_pxScrollbarButton->SetBorderWidth( 0.5f );
	m_pxScrollbarButton->SetImage( GetStringHash( "ScrollVert16" ) );
	m_pxScrollbarButton->SetImageMargin( 2 );
}

ScrollBar::~ScrollBar()
{
	// Do I need to do anything here? I don't think I do...
}

void ScrollBar::SetHorizontal( const bool bHorizontal )
{ 
	m_bHorizontal = bHorizontal;
	m_pxScrollbarButton->SetImage( GetStringHash( "ScrollHorz16" ) );
}

void ScrollBar::Render()
{
	if( !m_bVisible )
	{
		return;
	}
	
	u_int uScrollbarLength = m_uHeight;
	
	if( m_bHorizontal )
	{
		uScrollbarLength = m_uWidth;
	}
	
	m_uScrollHandleLength = (u_int)( (float)uScrollbarLength * (float)uScrollbarLength / (float)m_uParentContentSize );
	
	glBindTexture( GL_TEXTURE_2D, INVALID_TEXTURE_ID );
	
	const u_int uSwappedBackColour = MathsHelper::RGBAtoABGR( uSCROLLBAR_BACKGROUND );
	glColor4ubv( reinterpret_cast<const GLubyte*>( &uSwappedBackColour ) );
	
	// Draw background
	glBegin( GL_QUADS );

	if( m_bHorizontal )
	{
		glVertex2i( m_pxParent->GetResizedX() + 1, 
					m_pxParent->GetResizedHeight() + m_pxParent->GetResizedY() - uSCROLLBAR_WIDTH - 1);
		
		glVertex2i( m_pxParent->GetResizedX() + m_pxParent->GetResizedWidth() - ( m_bUsingBothBars ? uSCROLLBAR_WIDTH : 0 ) - 1,
					m_pxParent->GetResizedHeight() + m_pxParent->GetResizedY() - uSCROLLBAR_WIDTH - 1 );
		
		glVertex2i( m_pxParent->GetResizedX() + m_pxParent->GetResizedWidth() - ( m_bUsingBothBars ? uSCROLLBAR_WIDTH : 0 ) - 1, 
					m_pxParent->GetResizedHeight() + m_pxParent->GetResizedY() - 1 );
		
		glVertex2i( m_pxParent->GetResizedX() + 1, 
					m_pxParent->GetResizedHeight() + m_pxParent->GetResizedY() - 1);
				
		m_iMinTrackPos = static_cast<int>( m_uScrollHandleLength / 2.0f );
		m_iMaxTrackPos = ( m_pxParent->GetResizedWidth() - ( m_bUsingBothBars ? uSCROLLBAR_WIDTH : 0 ) - 2 ) - ( m_uScrollHandleLength / 2 );
	}
	else
	{
		glVertex2i( m_pxParent->GetResizedX() + m_pxParent->GetResizedWidth() - uSCROLLBAR_WIDTH - 1, 
					m_pxParent->GetResizedY() + 1 );
		
		glVertex2i( m_pxParent->GetResizedX() + m_pxParent->GetResizedWidth() - 1, 
					m_pxParent->GetResizedY() + 1 );
		
		glVertex2i( m_pxParent->GetResizedX() + m_pxParent->GetResizedWidth() - 1, 
					m_pxParent->GetResizedY() + m_pxParent->GetResizedHeight() - ( m_bUsingBothBars ? uSCROLLBAR_WIDTH : 0 ) - 1 );
		
		glVertex2i( m_pxParent->GetResizedX() + m_pxParent->GetResizedWidth() - uSCROLLBAR_WIDTH - 1, 
					m_pxParent->GetResizedY() + m_pxParent->GetResizedHeight() - ( m_bUsingBothBars ? uSCROLLBAR_WIDTH : 0 ) - 1 );
		
		m_iMinTrackPos = static_cast<int>( m_uScrollHandleLength / 2.0f );
		m_iMaxTrackPos = ( m_pxParent->GetResizedHeight() - ( m_bUsingBothBars ? uSCROLLBAR_WIDTH : 0 ) - 2 ) - ( m_uScrollHandleLength / 2 );	
	}
	
	glEnd();
	
	m_pxScrollbarButton->Render();
}

void ScrollBar::Update()
{	
	if( !m_bEnabled )
	{
		m_uPositionX =
		m_uPositionY =
		m_uWidth =
		m_uHeight = 0;
		
		return;
	}
	
	m_pxScrollbarButton->Update();
	
	// Set proper position and size for mouse detection
	if( m_bHorizontal )
	{
		m_uPositionX = m_pxParent->GetResizedX(); 
		m_uPositionY = m_pxParent->GetResizedHeight() + m_pxParent->GetResizedY() - uSCROLLBAR_WIDTH;
		m_uWidth = m_iParentVisableSize + 2;
		m_uHeight = uSCROLLBAR_WIDTH + 1;
	}
	else 
	{
		m_uPositionX = m_pxParent->GetResizedX() + m_pxParent->GetResizedWidth() - uSCROLLBAR_WIDTH - 1;
		m_uPositionY = m_pxParent->GetResizedY();
		m_uWidth = uSCROLLBAR_WIDTH + 1;
		m_uHeight = m_iParentVisableSize + 2;
	}	
	
	const Input* pxInput = Controller_Main::GetInputHandler();
	
	int iMousePos = pxInput->MousePositionY();
	int iWindowSize = m_pxParent->GetResizedY();
	int iScrollbarLength = m_uHeight;

	if( m_bHorizontal )
	{
		iMousePos = pxInput->MousePositionX();
		iWindowSize = m_pxParent->GetResizedX();
		iScrollbarLength = m_uWidth;
	}
	
	if( m_uScrollHandleLength >= (u_int)iScrollbarLength )
	{
		m_pxScrollbarButton->SetVisible( false );
		m_pxScrollbarButton->SetEnabled( false );
		return;
	}
	
	int iRemappedBarPos = static_cast<int>( MathsHelper::Remap<float>( (float)m_iScrollbarOffset, 0.0f, (float)( m_uParentContentSize - iScrollbarLength ), (float)m_iMinTrackPos, (float)m_iMaxTrackPos ) );
	iRemappedBarPos = MathsHelper::Clamp( iRemappedBarPos, m_iMinTrackPos, m_iMaxTrackPos );
		
	m_pxScrollbarButton->SetVisible( true );
	m_pxScrollbarButton->SetEnabled( true );
	
	if( m_bHorizontal )
	{
		m_pxScrollbarButton->SetPosition( static_cast<u_int>( m_pxParent->GetResizedX() + iRemappedBarPos - float( m_uScrollHandleLength / 2 ) + 1.0f ), 
   										  static_cast<u_int>( m_pxParent->GetResizedHeight() + m_pxParent->GetResizedY() - (float)uSCROLLBAR_WIDTH + 0.5f ) );
		m_pxScrollbarButton->SetSize( m_uScrollHandleLength, uSCROLLBAR_WIDTH );
	}
	else
	{
		m_pxScrollbarButton->SetPosition( static_cast<u_int>( m_pxParent->GetResizedX() + m_pxParent->GetResizedWidth() - (float)uSCROLLBAR_WIDTH + 0.5f ), 
										  static_cast<u_int>( iWindowSize + iRemappedBarPos - float( m_uScrollHandleLength / 2 ) ) );
		m_pxScrollbarButton->SetSize( uSCROLLBAR_WIDTH, m_uScrollHandleLength );
	}
	
	// Move the handle if we're dragging it
	if( m_bMouseDownState && pxInput->MouseMoved() )
	{
		int iMouseStartPoint = m_iScrollDragStartOffset - m_iMouseStartOffset;
		int iMouseDiff = ( iMousePos - iWindowSize ) - iMouseStartPoint;
		
		m_iScrollbarOffset = (int)MathsHelper::Clamp( 
			MathsHelper::Remap( float( m_iScrollDragStartOffset + iMouseDiff ), (float)m_iMinTrackPos, (float)m_iMaxTrackPos, 0.0f, float( m_uParentContentSize - iScrollbarLength ) )
			, 0.0f, float( m_uParentContentSize - iScrollbarLength ) );
	}
	
	else if( pxInput->MouseButtonPressed( INPUT_MOUSE_BUTTON_LEFT ) && MouseInWidget() )
	{					
		m_bMouseDownState = true;
		
		// Clicked on the handle
		if( iMousePos > ( iWindowSize + iRemappedBarPos ) - (int)( (int)m_uScrollHandleLength / 2 ) + 1 && 
			iMousePos < ( iWindowSize + iRemappedBarPos ) + (int)( (int)m_uScrollHandleLength / 2 ) + 1 ) 
		{
			// Record intial state on click
			m_iMouseStartOffset = ( iWindowSize + iRemappedBarPos ) - iMousePos;
			m_iScrollDragStartOffset = iRemappedBarPos;
		}	
		else
		{
			
		}
	}
	
	if( pxInput->MouseButtonReleased( INPUT_MOUSE_BUTTON_LEFT ) )
	{
		m_bMouseDownState = false;
	}

	
	Widget::Update();
}

void ScrollBar::SetScrollbarOffset( const int iScrollbarOffset )
{
	if( iScrollbarOffset < 0 )
	{
		return;
	}
	
	m_iScrollbarOffset = iScrollbarOffset;
}

// eof
